package com.mt.api.modules.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.mt.common.enums.AppReturnCodeEnum;
import com.mt.common.response.WebResponse;
import com.mt.common.response.WebResponseUtils;
import com.mt.common.utils.RedisUtils;
import com.mt.api.constants.constant.Constants;
import com.mt.api.constants.enums.AccountTypeEnum;
import com.mt.api.constants.enums.MobileLoginTypeEnum;
import com.mt.api.constants.enums.UserLevelEnum;
import com.mt.api.core.sms.SmsSend;
import com.mt.api.core.sms.SmsUtils;
import com.mt.api.modules.domain.*;
import com.mt.api.modules.domain.bo.AppPhoneLoginBo;
import com.mt.api.modules.domain.bo.PhoneRegisterBo;
import com.mt.api.modules.manager.*;
import com.mt.api.modules.service.IAppLoginService;
import com.mt.api.util.JwtUserUtils;
import com.mt.api.util.PasswordUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Objects;


/**
 * @Author: plover
 * @Date: 2022/01/02 8:12 下午
 * @Description:
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AppLoginServiceImpl implements IAppLoginService {

    private final IBossManager bossManager;
    private final IBossBrandManager bossBrandManager;
    private final IBrandManager brandManager;
    private final IBossRoleManager bossRoleManager;
    private final IRoleManager roleManager;
    private final IBossSetupManager bossSetupManager;

    private final RedisUtils redisUtils;

    private final String REDIS_PHONE_VCODE_PREFIX_KEY = "phone:vcode:";

    @Override
    public WebResponse mobileLogin(AppPhoneLoginBo appPhoneLoginBo) {
        JSONObject result = new JSONObject();
        if (Objects.equals(MobileLoginTypeEnum.CODE.getCode(), appPhoneLoginBo.getLoginType())) {
            String key = REDIS_PHONE_VCODE_PREFIX_KEY + appPhoneLoginBo.getPhone();
            if (!redisUtils.hasKey(key)) {
                return WebResponseUtils.error(AppReturnCodeEnum.LOGIN_ERROR_EXPIRED_VCODE);
            }
            String vCode = redisUtils.get(REDIS_PHONE_VCODE_PREFIX_KEY + appPhoneLoginBo.getPhone()).toString();
            if (StringUtils.isBlank(vCode) || !StringUtils.equals(vCode, appPhoneLoginBo.getCode())) {
                //如果验证码为空，或者不相等，则登录失败
                return WebResponseUtils.error(AppReturnCodeEnum.LOGIN_ERROR_WRONG_VCODE);
            }
            AppBoss appBoss = bossManager.getBossByPhone(appPhoneLoginBo.getPhone());
            //手机号不存在，则创建账号
            if (Objects.isNull(appBoss)) {
                return WebResponseUtils.error(AppReturnCodeEnum.LOGIN_ERROR_PHONE_NOT_EXIST);
            }
            result = JwtUserUtils.handlerLoginInfo(appBoss);
            //删除验证码缓存
            redisUtils.del(REDIS_PHONE_VCODE_PREFIX_KEY + appPhoneLoginBo.getPhone());
            return WebResponseUtils.success(result);
        } else if (Objects.equals(MobileLoginTypeEnum.PASSWORD.getCode(), appPhoneLoginBo.getLoginType())) {
            AppBoss appBoss = bossManager.getBossByPhone(appPhoneLoginBo.getPhone());
            //手机号不存在
            if (Objects.isNull(appBoss)) {
                return WebResponseUtils.error(AppReturnCodeEnum.LOGIN_ERROR_PHONE_NOT_EXIST);
            }
            String md5HexPass = DigestUtils.md5Hex(appPhoneLoginBo.getPassword());
            //密码错误
            if (!StringUtils.equals(md5HexPass, appBoss.getPassword())) {
                return WebResponseUtils.error(AppReturnCodeEnum.LOGIN_ERROR_WRONG_PASSWORD);
            }
            //TODO 校验其他账号信息
            result = JwtUserUtils.handlerLoginInfo(appBoss);
            return WebResponseUtils.success(result);
        }
        return WebResponseUtils.error(AppReturnCodeEnum.LOGIN_ERROR_WRONG_LOGIN_TYPE);
    }


    @Override
    public WebResponse sendCode(AppPhoneLoginBo appPhoneLoginBo) {
        String key = REDIS_PHONE_VCODE_PREFIX_KEY + appPhoneLoginBo.getPhone();
        if (redisUtils.hasKey(key)) {
            return WebResponseUtils.error("短信验证码5分钟有效，请勿重复发送");
        }

        String code = RandomStringUtils.random(4, false, true);
        JSONObject param = new JSONObject();
        param.put("code", code);
        SmsSend smsSend = new SmsSend();
        smsSend.setPhoneNumbers(appPhoneLoginBo.getPhone());
        smsSend.setTemplateCode("SMS_137845237");
        smsSend.setTemplateParam(param);
        SmsUtils.send(smsSend);
        //验证码有效期300秒
        redisUtils.set(key, code, 300);
        return WebResponseUtils.success();
    }

    @Override
    public WebResponse verifyCode(AppPhoneLoginBo appPhoneLoginBo) {
        String key = REDIS_PHONE_VCODE_PREFIX_KEY + appPhoneLoginBo.getPhone();
        if (!redisUtils.hasKey(key)) {
            return WebResponseUtils.error("手机号验证码已过期");
        }
        String redisCode = redisUtils.get(REDIS_PHONE_VCODE_PREFIX_KEY + appPhoneLoginBo.getPhone()).toString();
        if (!StringUtils.equals(appPhoneLoginBo.getCode(), redisCode)) {
            return WebResponseUtils.error(AppReturnCodeEnum.LOGIN_ERROR_WRONG_VCODE);
        }
        return WebResponseUtils.success();
    }

    @Override
    public WebResponse register(PhoneRegisterBo bo) {
        AppBoss bossByPhone = bossManager.getBossByPhone(bo.getPhone());
        if (Objects.nonNull(bossByPhone)) {
            return WebResponseUtils.error("手机号已注册");
        }
        Date now = new Date();
        AppBoss boss = new AppBoss();
        boss.setAccount(bo.getPhone());
        boss.setPhone(bo.getPhone());
        boss.setAccountType(AccountTypeEnum.PRIMARY.getCode());
        boss.setPassword(PasswordUtil.encryptPassword(bo.getPassword(), StringUtils.EMPTY));
        boss.setName(bo.getName());
        boss.setUserType(Constants.UserType.MERCHANT);
        boss.setUserLevel(UserLevelEnum.V3.getCode());

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(now);
        calendar.add(Calendar.MONTH, 1);
        boss.setRegDate(now);
        boss.setExpiryDate(calendar.getTime());
        boss.setStatus(Constants.AccountState.NORMAL);
        boss.setLastLoginTime(now);
        bossManager.save(boss);

        //品牌不做校验，每次注册都当做一个新品牌
        AppBrand brand = new AppBrand();
        //保存品牌信息
        brand.setBrandName(bo.getBrandName());
        brand.setHouseNo(bo.getHouseNo());
        brand.setMarketName(bo.getMarketName());
        brandManager.save(brand);

        //保存账号品牌关系
        AppBossBrand bossBrand = new AppBossBrand();
        bossBrand.setBrandId(brand.getId());
        bossBrand.setBossId(boss.getId());
        bossBrandManager.save(bossBrand);

        //设置用户默认角色
        List<Role> sysRoleList = roleManager.getSysRoleList();
        List<BossRole> roleList = Lists.newArrayList();
        for (Role role : sysRoleList) {
            BossRole bossRole = new BossRole();
            bossRole.setBossId(boss.getId());
            bossRole.setRoleId(role.getId());
            roleList.add(bossRole);
        }
        bossRoleManager.saveBatch(roleList);

        //初始化账号默认设置
        AppBossSetup appBossSetup = new AppBossSetup();
        appBossSetup.setBossId(boss.getId());
        appBossSetup.setColors(Constants.DEFAULT_COLORS);
        appBossSetup.setSizes(Constants.DEFAULT_SIZES);
        appBossSetup.setQtyStepper(Constants.QTY_STEPPER);
        appBossSetup.setWarnVal(Constants.SKU_WARNVAL);
        bossSetupManager.save(appBossSetup);

        //注册之后，默认登录，处理登录相关
        JSONObject resultObj = JwtUserUtils.handlerLoginInfo(boss);
        return WebResponseUtils.success(resultObj);
    }

    @Override
    public WebResponse logout() {
        JwtUserUtils.removeRedisTokenInfo();
        return WebResponseUtils.success();
    }

}
